package at.mri.dogwatch.client.gin;

import javax.inject.Singleton;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.gwtplatform.mvp.client.gin.AbstractPresenterModule;
import com.gwtplatform.mvp.client.gin.DefaultModule;
import com.gwtplatform.mvp.client.proxy.Gatekeeper;

import at.mri.dogwatch.client.place.ClientPlaceManager;
import at.mri.dogwatch.client.pages.layout.MainPagePresenter;
import at.mri.dogwatch.client.pages.layout.MainPageView;
import at.mri.dogwatch.client.place.DefaultPlace;
import at.mri.dogwatch.client.place.LoggedInGateKeeper;
import at.mri.dogwatch.client.place.NameTokens;
import at.mri.dogwatch.client.pages.header.LoginHeaderPresenter;
import at.mri.dogwatch.client.pages.header.LoginHeaderView;
import at.mri.dogwatch.client.pages.newvideo.NewVideoPresenter;
import at.mri.dogwatch.client.pages.newvideo.NewVideoView;
import at.mri.dogwatch.shared.proxy.VideoProxy;
import at.mri.dogwatch.shared.services.VideoRequestFactory;
import at.mri.dogwatch.client.pages.newestfeed.LastVideosDataProvider;
import at.mri.dogwatch.client.pages.newestfeed.NewVideosFeedPresenter;
import at.mri.dogwatch.client.pages.newestfeed.NewVideosFeedView;
import at.mri.dogwatch.client.pages.videodetails.VideDetailsPresenter;
import at.mri.dogwatch.client.pages.videodetails.VideDetailsView;

public class ClientModule extends AbstractPresenterModule {

	@Override
	protected void configure() {
		install(new DefaultModule(ClientPlaceManager.class));

		bindPresenter(MainPagePresenter.class, MainPagePresenter.MyView.class,
				MainPageView.class, MainPagePresenter.MyProxy.class);

		bindConstant().annotatedWith(DefaultPlace.class).to(NameTokens.feed);

		bindPresenter(LoginHeaderPresenter.class,
				LoginHeaderPresenter.MyView.class, LoginHeaderView.class,
				LoginHeaderPresenter.MyProxy.class);

		bindPresenter(NewVideoPresenter.class,
				NewVideoPresenter.NewVideoView.class, NewVideoView.class,
				NewVideoPresenter.MyProxy.class);

		// bind the gatekeeper
		bind(Gatekeeper.class).to(LoggedInGateKeeper.class).asEagerSingleton();

		bindPresenter(NewVideosFeedPresenter.class,
				NewVideosFeedPresenter.MyView.class, NewVideosFeedView.class,
				NewVideosFeedPresenter.MyProxy.class);

		bind(AsyncVideoProvider.class);
		bind(new TypeLiteral<AsyncDataProvider<VideoProxy>>() {
		}).toProvider(AsyncVideoProvider.class);

		bindPresenter(VideDetailsPresenter.class,
				VideDetailsPresenter.MyView.class, VideDetailsView.class,
				VideDetailsPresenter.MyProxy.class);
		
		bind(VideoRequestContextProvider.class);
		
		bind(VideoRequestFactory.VideoRequestContext.class).toProvider(VideoRequestContextProvider.class);
	}

	@Provides
	@Singleton
	public VideoRequestFactory createVideoRequestFactory(EventBus eventBus) {
		VideoRequestFactory factory = GWT.create(VideoRequestFactory.class);
		factory.initialize(eventBus);
		return factory;
	}


	static class AsyncVideoProvider implements
			Provider<AsyncDataProvider<VideoProxy>> {

		@Inject
		VideoRequestFactory factory;

		@Override
		public AsyncDataProvider<VideoProxy> get() {
			return new LastVideosDataProvider(factory);
		}
	}

	static class VideoRequestContextProvider implements
			Provider<VideoRequestFactory.VideoRequestContext> {

		@Inject
		VideoRequestFactory factory;

		@Override
		public VideoRequestFactory.VideoRequestContext get() {
			return factory.videoRequest();
		}
	}

}
